#include "BluetoothObserver.h"
#include "../shark/include/Log.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <fcntl.h>
#include <termios.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/system_properties.h>
#include <android/log.h>
#include <poll.h>

#define MAX_BT_INFO 1024
#define MAX_COMMAND_LENGTH 1024*4
static unsigned char iap_count = 0;
static char iap_buffer[MAX_COMMAND_LENGTH] = { 0 };
static int serial_fd = -1;
static volatile int iap_running = 1;
static volatile int iap_socket_running = 1;
static int iap_rfcomm_socket = -1;
static int disableBluetooth = 0;

static char * wldeviceId = NULL;
//状态
char g_pair_status = 0; //0,pair failed,1,pair success
char g_iap_status = 0; //0,disconnect 1,connected 2 connecting
char g_bt_status = 0; //0,disconnect 1,connected
char g_remote_addr[MAX_BT_INFO] = { 0 };
char g_pair_addr[MAX_BT_INFO] = { 0 };
char g_local_addr[MAX_BT_INFO] = { 0 };

int write_at_cmd(char *data);
void (*pOnBluetoothRfcomm)(int wl_carplay);

static char* start_with(char*data, char* str) {
	if ('\0' == *str)
		return NULL;
	char* pos = data;
	char* sub = str;
	while (*sub == *pos && *sub != '\0') {
		++sub;
		++pos;
	}
	if (*sub == '\0') {
		return pos;
	} else {
		return NULL;
	}
}

int close_iap_rfcomm()
{
#if 1
	LOGV("close_iap_rfcomm\n");
	if(iap_rfcomm_socket > 0)
	{
		close(iap_rfcomm_socket);
	}
	iap_rfcomm_socket = -1;
	iap_socket_running = 0;
	return 0;
#endif
}

int open_iap_rfcomm() {
	int ret = 0;
	struct sockaddr_un addr;
	int fd;
	char sock_path[128] = { "/dev/socket/reverse_cp_socket" };//反向rfcomm socket通道
	const char *config_dir;

	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
		return -1;
	}

	memset(&addr, 0, sizeof(addr));
	addr.sun_family = AF_UNIX;
	strncpy(addr.sun_path, sock_path, sizeof(addr.sun_path) - 1);

	if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1) {
		LOGV("/dev/socket/reverse_cp_socket failed\n");
		close(fd);
		return -1;
	}
	LOGV("/dev/socket/reverse_cp_socket connect success\n");
	pthread_t thread;
	pthread_t tid;

	iap_socket_running = 1;
	iap_rfcomm_socket = fd;

	return 0;
}

unsigned char chartoi(char c) {
	if ((c >= 'A') && ((c <= 'F')))
		return (c - 'A' + 0x0A);
	if ((c >= 'a') && ((c <= 'f')))
		return (c - 'a' + 0x0A);
	if ((c >= '0') && ((c <= '9')))
		return (c - '0' + 0x00);
	return 0;
}

void timer_inquery_connect_func(int n)
{
    LOGV("timer_inquery_connect_func\n");
	write_at_cmd("AT#HR"); //inquery bt info
	write_at_cmd("AT#VR"); //inquery bt info
	write_at_cmd("AT#IR"); //inquery bt info
	write_at_cmd("AT#QI"); //inquery bt info
	write_at_cmd("AT#VE"); //inquery bt info
}
void init_time(int time) {
	struct itimerval val;

	val.it_value.tv_sec = time;
	val.it_value.tv_usec = 0;

	val.it_interval.tv_sec = 0;
	val.it_interval.tv_usec = 0;

	setitimer(ITIMER_REAL, &val, NULL);
	LOGV("init_time time=%d\n", time);
}

static void on_handle_at_cmd() {
	char * data;
	static char pair_status = -1;
	if ((data = start_with(iap_buffer, "IA")) != NULL
			|| (data = start_with(iap_buffer, "DT")) != NULL) {
		g_bt_status = 0;
		LOGV("bt disconnect\n");
		__system_property_set("sys.rwlbluetooth.connect.status", "0");
//		on_bluetooth_connect_state(0);
		if (g_iap_status == 1) {
//			disconnect_iap();
		}
		g_pair_status = 0;
		strcpy(g_remote_addr, "");
		g_iap_status = 0;
	} else if ((data = start_with(iap_buffer, "IB")) != NULL) {
		g_bt_status = 1;
		g_iap_status = 0;
		LOGV("bt connected\n");
		__system_property_set("sys.rwlbluetooth.connect.status", "1");
//		on_bluetooth_connect_state(1);
	}
	else if ((data = start_with(iap_buffer, "IP1")) != NULL) {
			LOGV("bt boot finish.\n");
			system("echo AT#SD >/dev/bt_serial");
			signal(SIGALRM, timer_inquery_connect_func);
			init_time(2);
	}
	else if ((data = start_with(iap_buffer, "DB")) != NULL) //bt local bd
	{
		strcpy(g_local_addr, data);
		LOGV("at recv g_local_addr:%s\n", g_local_addr);
        char bd_addr[6];
		int i;
		for (i = 0; i < 6; i++) {
			bd_addr[i] = chartoi(g_local_addr[i * 2]) * 16
					+ chartoi(g_local_addr[i * 2 + 1]);
		}

		LOGV("bt local bd_addr = %02X %02X %02X %02X %02X %02X \n",
				bd_addr[0],bd_addr[1],bd_addr[2],bd_addr[3],bd_addr[4],
				bd_addr[5]);
		if(wldeviceId != NULL)
		{
			free(wldeviceId);
		}
		wldeviceId = (char *)malloc(40);
		sprintf( wldeviceId,"%02X:%02X:%02X:%02X:%02X:%02X", bd_addr[0],
				bd_addr[1],bd_addr[2],bd_addr[3],bd_addr[4],bd_addr[5]);
		__system_property_set("sys.xq.product.deviceid",  wldeviceId);
	}
	else if ((data = start_with(iap_buffer, "IS")) != NULL) {
		LOGV("Tinker bt pair_status = %d g_pair_addr:%s \n", pair_status, data);
		char phoneType [20];
		char paired [20];
		char macAddr [20];
		memset(macAddr,0,20);
		memset(phoneType,0,20);
		memset(paired,0,20);

		strncpy(phoneType, data, 1);
		strncpy(paired, data+1, 1);
		strncpy(macAddr, data+2, 12);

		strcpy(g_pair_addr, macAddr);
		strcpy(g_remote_addr, macAddr);

        char bd_addr[6];
		int i;
		for (i = 0; i < 6; i++) {
			bd_addr[i] = chartoi(g_remote_addr[i * 2]) * 16
					+ chartoi(g_remote_addr[i * 2 + 1]);
		}

		LOGV("bt bd_addr = %02X %02X %02X %02X %02X %02X \n",
				bd_addr[0],bd_addr[1],bd_addr[2],bd_addr[3],bd_addr[4],
				bd_addr[5]);

		pair_status = 1;
		g_pair_status = 1;
		LOGV("bt pair_status = %d g_pair_addr:%s \n", pair_status, macAddr);

        if (iap_rfcomm_socket < 0) {
            open_iap_rfcomm();
        }
        LOGV("bt connected\n");
        __system_property_set("sys.rwlbluetooth.connect.status", "1");
//        on_bluetooth_connect_state(1);
        LOGV("VS = %s\n", iap_buffer);
        // VS0101GOC11
        int phone = atoi( phoneType );
        LOGV("bt connected,phone = %d \n",phone);
        if(phone)
        {
        	LOGV("bt connected,phone is iPhone \n");
//        	connect_carplay_wl(bd_addr, g_local_addr, 1);
        }else{
        	LOGV("bt connected,phone is Android %p \n",pOnBluetoothRfcomm);
//        	connect_androidauto_wl(bd_addr, g_local_addr, 0);
        	if(pOnBluetoothRfcomm != NULL )
        	{
        		LOGV("bt connected,phone is WirelessCarPlay,start connection. \n");
        		pOnBluetoothRfcomm(1);
        	}
        }
	}
}

static void on_char_iap(char c) {
	if (iap_count + 2 == MAX_COMMAND_LENGTH) {
		iap_count = 0;
		return;
	}
	if ('\r' == c || '\n' == c) {
		if (iap_count == 0)
			return;
		iap_buffer[iap_count++] = '\0';
		LOGV("carplay at command len = %d:%s\n", strlen(iap_buffer), iap_buffer);
		on_handle_at_cmd();
		iap_count = 0;
	} else {
		iap_buffer[iap_count++] = c;
	}
}

#define MAX_COMMAND_LENGTH 1024*4
static void *bt_AT_cmd_process(void *param_fd) {
	char buffer[MAX_COMMAND_LENGTH];
	long server = (long) param_fd;
	if (server <= 0) {
		return 0;
	}

	while (1) {
		if (!iap_running)
			break;
		memset(buffer, 0, MAX_COMMAND_LENGTH);
		int len = read(server, buffer, MAX_COMMAND_LENGTH);
		if (len <= 0) {
			usleep(500);
			continue;
		}
		LOGV("bt_AT_cmd_process: len = %d:%s\n", len, buffer);
		for (int i = 0; i < len; i++) {
			on_char_iap(buffer[i]);
		}
	}
	close(server);
	return NULL;
}

int open_bt_uart() {

	int ret = -1;
	char uartval[50] = { 0 };
	struct termios tty;
	char buffer[MAX_COMMAND_LENGTH];
	LOGV("open_bt_uart start\n");

	strcpy(uartval, "/dev/reverse_cp_serial"); //反向命令节点
	LOGV("Try to open port: %s.\n", uartval);
	int fd = open(uartval, O_RDWR | O_NOCTTY);
	if (fd <= 0) {
		LOGV("failed to open %s:%s.\n", uartval, strerror(errno));
		return -1;
	}
	/* Set raw attributes on the pty. */
	tcgetattr(fd, &tty);
	cfmakeraw(&tty);
	tcsetattr(fd, TCSAFLUSH, &tty);

	pthread_t thread;
	pthread_t tid;

	iap_running = 1;
	serial_fd = fd;
	ret = pthread_create(&tid, NULL, bt_AT_cmd_process, (void*) fd);
	if (ret != 0) {
		LOGV("create bt_AT_cmd_process thread error\n");
		return -1;
	}

//	signal(SIGALRM, timer_inquery_connect_func);
//	init_time(2);
	LOGV("open_bt_uart end\n");
	return 0;
}

int write_at_cmd(char *data) {
	if (serial_fd <= 0)
		return 0;

	char cmd[1024] = { 0 };
	strcpy(cmd, data);
	strcat(cmd, "\r\n");

	write(serial_fd, cmd, strlen(cmd));
	LOGV("write_at_cmd len=%d::%s\n", strlen(cmd), cmd);
	return strlen(data);
}

void observe_bluetooth_rfcomm(  void (*pFunc)(int wl_carplay) )
{
	pOnBluetoothRfcomm = pFunc;
	LOGD("observe_bluetooth_rfcomm \n");
	system("echo AT#P1 >/dev/bt_serial");
//	usleep(1200);
	open_bt_uart();

}

int readRfcomm(uint8 *data, uint16 outlen,int * outlength)
{
//	LOGD( "%s:%d \n", __func__, __LINE__);
	if( disableBluetooth == 1)
	{
		sleep(2);
		return 0;
	}
	int len = 0;
	int rc = 0;
	struct pollfd pfd;

	if (!iap_socket_running){
//		LOGD( "%s:%d \n", __func__, __LINE__);
		return 0;
	}

	pfd.fd = iap_rfcomm_socket;
	pfd.events = POLLIN | POLLHUP | POLLRDNORM;
	pfd.revents = 0;

	rc = poll(&pfd, 1, 100);
	if (rc == 0)
	{
//		LOGD( "timeout %s:%d \n", __func__, __LINE__);
		//timeout
		return 0;
	}

	if(rc > 0)
	{
		len = read(iap_rfcomm_socket, data, outlen);
	}

	if (len <= 0) {
//		LOGD( "%s:%d \n", __func__, __LINE__);
		return 0;
	}
#if 0
	if (len > 0) {
		LOGV("carplay_readIap2DataProc len=%d\n", len);
		char tmp[4096] = { 0 };
		memset(tmp, 0, 4096);

		for (int i = 0; i < len; i++) {
			sprintf(tmp + i * 2, "%02X", data[i]);
		}
		LOGV("reverse wlcarplay_readIap2DataProc:%s\n", tmp);

	}
#endif
	outlen = len;
	*outlength = len;

	return outlen;
}

int writeRfcomm(uint8 *data, uint16 len,int * length)
{
	if( disableBluetooth == 1)
	{
		sleep(2);
		return 0;
	}
	long server = (long) iap_rfcomm_socket;
	if (server <= 0) {
		return 0;
	}
	if (!iap_socket_running){
		return 0;
	}
#if 0
	char buffer[4096] = { 0 };
	memset(buffer, 0, 4096);

	for (int i = 0; i < len; i++) {
		sprintf(buffer + i * 2, "%02X", data[i]);
	}
	LOGV("reverse wlcarplay_send_iap_data_socket:%s\n", buffer);
#endif
	write(iap_rfcomm_socket, data, len);
	*length = len;
	return 0;
}

int disconnectRfcomm()
{
	LOGV("disconnectRfcomm \n");
	disableBluetooth = 1;
	system("echo AT#SH > /dev/bt_serial");
	return 0;
}
